package com.pep.mgmt.service;

import java.util.List;

import org.springframework.stereotype.Component;

import com.pep.mgmt.controller.ConfigurationController;
import com.pep.mgmt.model.entity.ConfigEntity;
import com.pep.mgmt.model.entity.RcstIpTablesRule;
import com.pep.mgmt.model.entity.VrfEntity;
import com.pep.mgmt.util.CONST;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class StartupService {

    private final SchedulerService schedulerService;
    private final ConfigurationController configurationController;
    private final PepMgmtService pepMgmtService;
    private final ShellCmdService shellCmdService;

    public StartupService(SchedulerService schedulerService, ConfigurationController configurationController, 
                                PepMgmtService pepMgmtService, ShellCmdService shellCmdService) {
        this.schedulerService = schedulerService;
        this.configurationController = configurationController;
        this.pepMgmtService = pepMgmtService;
        this.shellCmdService = shellCmdService;
    }

    private void utilCleanupLogFiles() {
        schedulerService.logFileCleanup();
    }

    private void utilKillRunningPrograms() {
        if (CONST.TEST_MODE)
            shellCmdService.someMethod("killall " + CONST.TEST_PROGRAM_NAME);
        else {
            //need to cleanup all sub-chain entrances
            String runCmd = "./bash/white_list.sh disable 0.0.0.0 all";
            log.info("runCmd {}", runCmd);
            String result = shellCmdService.someMethod(runCmd);
            log.info("result white_list.sh {}", result);

            shellCmdService.someMethod("killall " + CONST.PEP_PROGRAM_NAME);
        }
    }

    private void utilCleanupAllIpTablesRules() {
        List<VrfEntity> vrfEntities = pepMgmtService.findAllVrfs();
        for (VrfEntity vrfEntity: vrfEntities) {
            String runCmd = "./bash/white_list.sh del vrf " + vrfEntity.getVrfName() + " all";
            log.info("runCmd {}", runCmd);
            String result = shellCmdService.someMethod(runCmd);
            log.info("result white_list.sh {}", result);
        }
    }

    private void utilCleanupAllVrfs() {
        String result = shellCmdService.someMethod("./bash/del_vrf.sh all");
        log.info("result del_vrf.sh {}", result);
    }

    private void utilSetupVrfsFromDB() {
        List<VrfEntity> vrfEntities = pepMgmtService.findAllVrfs();
        for (VrfEntity vrfEntity: vrfEntities) {
            String result = shellCmdService.someMethod("./bash/add_vrf.sh " + vrfEntity.getVlanId() + " " + vrfEntity.getVlanIpAddr() + " " + vrfEntity.getDefaultGW());
            log.info("result add_vrf.sh {}", result);
        }
    }

    private void utilSetupIpTablesRulesFromDB() {

        List<RcstIpTablesRule> rcstIpTablesRules = pepMgmtService.getAllRcstIpTableRules();
        for (RcstIpTablesRule rcstIpTablesRule: rcstIpTablesRules) {
            //run script to create iptables rules
            String runCmd = "./bash/white_list.sh add " + rcstIpTablesRule.getVrfName() + " " + rcstIpTablesRule.getIptablesRules();
            log.info("runCmd {}", runCmd);
            String result = shellCmdService.someMethod(runCmd);
            log.info("result white_list.sh {}", result);
        }
    }

    private void utilGenDefaultConfig() {
        
        log.info("generate the default configuration files");
        ConfigEntity ce = new ConfigEntity();
        ce.setClientTcpAlgo("cubic");
        ce.setTunnelTcpAlgo("cubic");
        ce.setTunnelTcpHighWaterMark((long)8*1024*1024);
        ce.setTunnelTcpLowWaterMark((long)5*1024*1024);
        ce.setClientTcpHighWaterMark((long)1*1024*1024);
        ce.setClientTcpRecvBuffer(0);
        pepMgmtService.updateConfig(ce, true);
        
        List<RcstIpTablesRule> rcstIpTablesRules = pepMgmtService.getAllRcstIpTableRules();
        for (RcstIpTablesRule rcstIpTablesRule: rcstIpTablesRules) {
            String fileName = rcstIpTablesRule.getRcstIpAddr() + "_" + rcstIpTablesRule.getVrfName();
            boolean result = pepMgmtService.saveConfigToFile(fileName, CONST.CONFIG_FILE_PATH, rcstIpTablesRule.getIptablesRules());
            if (result) {
                log.info("create config file {} successfully", fileName);
            } else {
                log.warn("failed to creat config file {}", fileName);
            }
        }
    }

    @PostConstruct
	public void launchAll() {
        log.info("launchAll");

        utilKillRunningPrograms();
        utilCleanupLogFiles();
        utilGenDefaultConfig();

        if (!CONST.TEST_MODE) {
            utilCleanupAllIpTablesRules();
            utilCleanupAllVrfs();
            utilSetupVrfsFromDB();
            utilSetupIpTablesRulesFromDB();
        }

        schedulerService.startSchedulerService();
        configurationController.startConfigurationController();
    }

    @PreDestroy
    void preStopAll() throws InterruptedException {

        log.info("preStopAll");
        schedulerService.stopSchedulerService();
        configurationController.stopConfigurationController();

        utilKillRunningPrograms();
        if (!CONST.TEST_MODE) {
            utilCleanupAllIpTablesRules();
            utilCleanupAllVrfs();
        }
    }
}